package retrieval;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;

import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;

import ui.xmlVisualization.XMLTree;

/**
 * This class is used to generator DTD from a set of XML files
 * 
 * @author eDisOn
 * @version 0.1
 */
public class XRetrievalTreeGenerator
{
	private Document XRetrievalTree = null;

	/**
	 * Default construction
	 */
	public XRetrievalTreeGenerator()
	{
	}

	public Document generate(ArrayList<ArrayList<String>> queryResultList)
	{
		/* create default XRetrievalTree with only root element */
		this.XRetrievalTree = DocumentHelper.createDocument();
		this.XRetrievalTree.addElement("Result");

		for (ArrayList<String> queryResult : queryResultList)
		{
			this.parseResult(queryResult);
		}

		return this.XRetrievalTree;
	}

	/**
	 * Parse each query result to explore new element node in XRetrievalTree
	 * 
	 * @param queryResult
	 *            Each query result to be parsed
	 * @return true if pares succeed, false otherwise
	 */
	private boolean parseResult(ArrayList<String> queryResult)
	{
		try
		{
			Document doc = this.result2DOM(queryResult);

			Element queryResultRoot = doc.getRootElement();
			Element XRetrievalTreeRoot = this.XRetrievalTree.getRootElement();

			this.exploreNode(queryResultRoot, XRetrievalTreeRoot);

			return true;
		} catch (Exception ex)
		{
			ex.printStackTrace();
			return false;
		}
	}

	private Document result2DOM(ArrayList<String> queryResult)
	{
		Document QRDom = DocumentHelper.createDocument();

		Element currentElement = QRDom.addElement("Result");
		for (String item : queryResult)
		{
			currentElement = currentElement.addElement(item);
		}
		return QRDom;
	}

	/**
	 * Explore new element nodes in the XRetrievalTree and which are not
	 * included in XRetrievalTree
	 * 
	 * @param queryResultNode
	 *            Current query result node
	 * @param XRetrievalTreeNode
	 *            Current analysis XRetrievalTreeNode node
	 */
	private void exploreNode(Element queryResultNode, Element XRetrievalTreeNode)
	{
		/* find all children element of current XRetrievalTree node */
		ArrayList<Element> DTDElemList = new ArrayList<Element>();
		for (Iterator DTDIt = XRetrievalTreeNode.elementIterator(); DTDIt
				.hasNext();)
		{
			Element DTDElem = (Element) DTDIt.next();
			DTDElemList.add(DTDElem);
		}

		/* traverse the xml tree to explore new node and then add them into DTD */
		for (Iterator queryResultIt = queryResultNode.elementIterator(); queryResultIt
				.hasNext();)
		{
			Element childElem = (Element) queryResultIt.next();

			/* if XRetrievalTree has already contained this element node */
			Element respondElem = this.contains(DTDElemList, childElem);
			if (respondElem != null)
			{
				// explore child node
				this.exploreNode(childElem, respondElem);
			}

			/*
			 * if XRetrievalTree has not contains this element node then insert
			 * it into XRetrievalTree
			 */
			else
			{
				String newDTDNodeName = childElem.getName();
				Element newDTDNode = XRetrievalTreeNode
						.addElement(newDTDNodeName);
				this.exploreNode(childElem, newDTDNode);
			}
		}
	}

	/**
	 * Return true if the DTDELemList contains this XMLElement
	 * 
	 * @param DTDElemList
	 *            DTD element list
	 * @param XMLElement
	 *            The XML element to search for
	 * 
	 * @return This element object if the DTDELemList contains this XMLElement,
	 *         null otherwise
	 */
	private Element contains(ArrayList<Element> DTDElemList, Element XMLElement)
	{
		String XMLElemName = XMLElement.getName();
		for (Element DTDElem : DTDElemList)
		{
			String DTDElemInfo = DTDElem.getName();
			int delim = DTDElemInfo.indexOf("_");
			String DTDElmeName = DTDElemInfo.substring(delim + 1);

			if (DTDElmeName.equals(XMLElemName))
			{
				return DTDElem;
			}
		}
		return null;
	}

	/**
	 * Display the DTD file
	 * 
	 * @throws IOException
	 */
	public void display(Document xretrievalTree) throws IOException
	{
		XMLTree.showTree(xretrievalTree);

		/* Pretty print to the console */
		XMLWriter writer = new XMLWriter();
		OutputFormat format = OutputFormat.createPrettyPrint();
		writer = new XMLWriter(System.out, format);
		writer.write(xretrievalTree);
		writer.close();
	}
}
